package com.shihan.rabbitmq.advancedfeatures.controller;

import com.shihan.rabbitmq.advancedfeatures.config.RabbitMQConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;

/**
 * @Description 测试 publisherConfirm 用的业务 controller
 * @Author shihan
 * @Date 2021/1/2 11:51
 * @Version 1.0
 */
@RestController
public class BizController {

    private RabbitTemplate rabbitTemplate;

    @Autowired
    private void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        // 当前 controller 类中使用的是 this.rabbitTemplate，@Autowired 注入的是 IOC 中的对象；
        // 此处是将 IOC 容器中的对象，做自定义修改后，再在本 controller 中使用.
        this.rabbitTemplate = rabbitTemplate;

        // 设置消息接收成功的 确认回调方法
        this.rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             * 这里和原生 API 操作方式不同，接收成功和失败都走这一个回调方法
             * 1、ack 为 true，取 correlationData 中的信息；
             * 2、ack 为 false，取 cause 中的信息；
             * @param correlationData   封装了消息的 ID 和 ReturnMessage 对象，CorrelationData 是在消息发送时，自己设置的对象；
             * @param ack               标识当前消息是成功接收（true），还是接收失败（false）
             * @param cause             消息接收失败的错误信息
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if(ack) {
                    // Broker 消息接收成功
                    System.out.println("Broker 消息接收成功！");
                    try {
                        System.out.println("消息ID：" + correlationData.getId() +
                                "，消息内容：" + new String(correlationData.getReturnedMessage().getBody(),"utf-8"));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    // Broker 消息接收失败
                    System.out.println("Broker 消息接收失败：" + cause);
                }
            }
        });
    }

    @GetMapping("/doBiz")
    public String doBiz() throws UnsupportedEncodingException {
        // 设置消息属性  TODO 关注一下 correlationId 和 consumerTag 属性的含义
        MessageProperties messageProperties = new MessageProperties();
        // messageProperties.setCorrelationId("1234");
        // messageProperties.setConsumerTag("msg_1");
        messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
        messageProperties.setContentEncoding("utf-8");

        // 创建 correlationData 对象  PS：需要注意一下 ID 属性，是否需要与 MessageProperties 中的哪个属性对应
        CorrelationData correlationData = new CorrelationData();
        // 因为这里的 ID 和 ReturnMessage 都是自己设置的，所以可以根据自己的需要，进行设置（比如和目标要发送的 Message 做上关联）
        correlationData.setId("msg_1");
        correlationData.setReturnedMessage( new Message("CorrelationData 中的 ReturnMessage.".getBytes("utf-8"),null) );

        // 实际发送目标消息
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.EXCHANGE_NAME_DIRECT,
                RabbitMQConfig.BINDING_KEY,
                new Message("当前实际需要发送的消息内容！".getBytes("utf-8"), messageProperties),
                correlationData
        );

        return "ok";
    }

    @GetMapping("/doBizFalse")
    public String doBizFalse() throws UnsupportedEncodingException {
        // 设置消息属性
        MessageProperties messageProperties = new MessageProperties();
        // messageProperties.setCorrelationId("1234");
        // messageProperties.setConsumerTag("msg_1");
        messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
        messageProperties.setContentEncoding("utf-8");

        // 实际发送目标消息
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.EXCHANGE_NAME_DIRECT,
                RabbitMQConfig.BINDING_KEY,
                new Message("当前实际需要发送的消息内容！".getBytes("utf-8"), messageProperties)
        );
        return "ok";
    }

}
